Tidy up the creation of directories that Xend needs. This avoids potential
authorEwan Mellor <ewan@xensource.com>
Fri, 1 Dec 2006 11:32:32 +0000 (11:32 +0000)
committerEwan Mellor <ewan@xensource.com>
Fri, 1 Dec 2006 11:32:32 +0000 (11:32 +0000)
races in this creation.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
tools/python/xen/util/mkdir.py [new file with mode: 0644]
tools/python/xen/util/xmlrpclib2.py
tools/python/xen/web/unix.py
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendLogging.py
tools/python/xen/xend/XendStorageRepository.py
tools/python/xen/xend/server/SrvDaemon.py

diff --git a/tools/python/xen/util/mkdir.py b/tools/python/xen/util/mkdir.py
new file mode 100644 (file)
index 0000000..121e498
--- /dev/null
@@ -0,0 +1,44 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (c) 2006 XenSource Inc.
+#============================================================================
+
+import errno
+import os
+import os.path
+import stat
+
+
+def parents(dir, perms, enforcePermissions = False):
+    """
+    Ensure that the given directory exists, creating it if necessary, but not
+    complaining if it's already there.
+    
+    @param dir The directory name.
+    @param perms One of the stat.S_ constants.
+    @param enforcePermissions Enforce our ownership and the given permissions,
+    even if the directory pre-existed with different ones.
+    """
+    # Catch the exception here, rather than checking for the directory's
+    # existence first, to avoid races.
+    try:
+        os.makedirs(dir, perms)
+    except OSError, exn:
+        if exn.args[0] != errno.EEXIST or not os.path.isdir(dir):
+            raise
+    if enforcePermissions:
+        os.chown(dir, os.geteuid(), os.getegid())
+        os.chmod(dir, stat.S_IRWXU)
index 3a3973f8382f8fc9e7f92d7ced8abf5027122821..efb29d7b0e54a1bee0cf951b7de175cc32c2f7df 100644 (file)
@@ -30,6 +30,8 @@ from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
 import SocketServer
 import xmlrpclib, socket, os, stat
 
+import mkdir
+
 from xen.web import connection
 from xen.xend.XendLogging import log
 
@@ -234,14 +236,9 @@ class UnixXMLRPCServer(TCPXMLRPCServer):
     address_family = socket.AF_UNIX
 
     def __init__(self, addr, allowed, logRequests = 1):
-        parent = os.path.dirname(addr)
-        if os.path.exists(parent):
-            os.chown(parent, os.geteuid(), os.getegid())
-            os.chmod(parent, stat.S_IRWXU)
-            if self.allow_reuse_address and os.path.exists(addr):
-                os.unlink(addr)
-        else:
-            os.makedirs(parent, stat.S_IRWXU)
+        mkdir.parents(os.path.dirname(addr), stat.S_IRWXU, True)
+        if self.allow_reuse_address and os.path.exists(addr):
+            os.unlink(addr)
 
         TCPXMLRPCServer.__init__(self, addr, allowed,
                                  UnixXMLRPCRequestHandler, logRequests)
index 8ec715c12faf19395b2faef5bfcaf737403fba9d..12b6e9694edb69401b25cf12222d392648a12526 100644 (file)
@@ -22,6 +22,8 @@ import os.path
 import socket
 import stat
 
+from xen.util import mkdir
+
 import connection
 
 
@@ -30,13 +32,9 @@ def bind(path):
 created such that only the current user may access it."""
 
     parent = os.path.dirname(path)
-    if os.path.exists(parent):
-        os.chown(parent, os.geteuid(), os.getegid())
-        os.chmod(parent, stat.S_IRWXU)
-        if os.path.exists(path):
-            os.unlink(path)
-    else:
-        os.makedirs(parent, stat.S_IRWXU)
+    mkdir.parents(parent, stat.S_IRWXU, True)
+    if os.path.exists(path):
+        os.unlink(path)
 
     sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
     sock.bind(path)
index 9a4d112e959d92bcf0381599c742984c4ac46335..bb14e70667763dd8534526a1845edca82bfa2aed 100644 (file)
@@ -23,6 +23,7 @@
 """
 
 import os
+import stat
 import shutil
 import socket
 import threading
@@ -44,7 +45,7 @@ from xen.xend.XendDevices import XendDevices
 
 from xen.xend.xenstore.xstransact import xstransact
 from xen.xend.xenstore.xswatch import xswatch
-from xen.util import security
+from xen.util import mkdir, security
 from xen.xend import uuid
 
 xc = xen.lowlevel.xc.xc()
@@ -99,11 +100,7 @@ class XendDomain:
         """Singleton initialisation function."""
 
         dom_path = self._managed_path()
-        try:
-            os.stat(dom_path)
-        except OSError:
-            log.info("Making %s", dom_path)
-            os.makedirs(dom_path, 0755)
+        mkdir.parents(dom_path, stat.S_IRWXU)
 
         xstransact.Mkdir(XS_VMROOT)
         xstransact.SetPermissions(XS_VMROOT, {'dom': DOM0_ID})
@@ -271,25 +268,17 @@ class XendDomain:
             domains_dir = self._managed_path()
             dom_uuid = dominfo.get_uuid()            
             domain_config_dir = self._managed_path(dom_uuid)
-        
-            # make sure the domain dir exists
-            if not os.path.exists(domains_dir):
-                os.makedirs(domains_dir, 0755)
-            elif not os.path.isdir(domains_dir):
-                log.error("xend_domain_dir is not a directory.")
-                raise XendError("Unable to save managed configuration "
-                                "because %s is not a directory." %
-                                domains_dir)
-            
-            if not os.path.exists(domain_config_dir):
+
+            def make_or_raise(path):
                 try:
-                    os.makedirs(domain_config_dir, 0755)
-                except IOError:
-                    log.exception("Failed to create directory: %s" %
-                                  domain_config_dir)
-                    raise XendError("Failed to create directory: %s" %
-                                    domain_config_dir)
-                
+                    mkdir.parents(path, stat.S_IRWXU)
+                except:
+                    log.exception("%s could not be created." % path)
+                    raise XendError("%s could not be created." % path)
+
+            make_or_raise(domains_dir)
+            make_or_raise(domain_config_dir)
+
             try:
                 sxp_cache_file = open(self._managed_config_path(dom_uuid),'w')
                 prettyprint(dominfo.sxpr(), sxp_cache_file, width = 78)
index a3d6de86d14ad75828badbe75114369799b45f48..32cd13c5dbbcc12b52c04c4210c96704278c596d 100644 (file)
 # Copyright (C) 2005, 2006 XenSource Ltd.
 #============================================================================
 
-
+import os
+import stat
 import tempfile
 import types
 import logging
 import logging.handlers
 import fcntl
 
+from xen.util import mkdir
 from xen.xend.server import params
 
 
@@ -80,6 +82,7 @@ def init(filename, level):
     global logfilename
 
     def openFileHandler(fname):
+        mkdir.parents(os.path.dirname(fname), stat.S_IRWXU)
         return XendRotatingFileHandler(fname, mode = 'a',
                                        maxBytes = MAX_BYTES,
                                        backupCount = BACKUP_COUNT)
index d906f5b5fd05f5ae030d50061fb221ae3b1c559a..a16a293191f5e257934a8ca85224c7cd7fc49617 100644 (file)
 # The default QCOW Xen API Storage Repository
 #
 
-import os
 import commands
+import os
+import stat
 import threading
 
+from xen.util import mkdir
 from xen.xend import uuid
 from xen.xend.XendError import XendError
 from xen.xend.XendVDI import *
@@ -98,10 +100,7 @@ class XendStorageRepository:
         """
         self.lock.acquire()
         try:
-            # create directory if /var/lib/xend/storage does not exist
-            if not os.path.exists(XEND_STORAGE_DIR):
-                os.makedirs(XEND_STORAGE_DIR)
-                os.chmod(XEND_STORAGE_DIR, 0700)
+            mkdir.parents(XEND_STORAGE_DIR, stat.S_IRWXU)
 
             # scan the directory and populate self.images
             total_used = 0
index 7bfa466dffe1f663107e13f8975556076bfae443..35c64869d41ac42cd8b8a9f87021f7ec6a474bbd 100644 (file)
@@ -21,6 +21,7 @@ import xen.lowlevel.xc
 
 from xen.xend.XendLogging import log
 from xen.xend import osdep
+from xen.util import mkdir
 
 import relocate
 import SrvServer
@@ -108,8 +109,7 @@ class Daemon:
         # so _before_ we close stderr.
         try:
             parent = os.path.dirname(XEND_DEBUG_LOG)
-            if not os.path.exists(parent):
-                os.makedirs(parent, stat.S_IRWXU)
+            mkdir.parents(parent, stat.S_IRWXU)
             fd = os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT|os.O_APPEND)
         except Exception, exn:
             print >>sys.stderr, exn